Customizing CRT Error Checking

The C run-time library provides run-time error checking when you compile with /RTC (run-time checks) or use the run-time_checks pragma. In some cases, you may want to customize CRT run-time error checking:

To customize run-time error checking, you can:

Writing a Run-Time Error Reporting Function

A custom reporting function for run-time errors must have same declaration as _CrtDbgReport. It should return value of 1 to the debugger.

The following example shows how to define a custom reporting function:

int errorhandler = 0;
void configureMyErrorFunc(int i)
{
   errorhandler = i;
}

int MyErrorFunc(int errorType, const char *filename, int linenumber, const char *moduleName, const char *format, ...) 
{
   switch (errorhandler)
   {
   case 0:
   case 1:
      printf("Error type %d at %s line %d in %s",errorType. filename, linenumber, moduleName);
   case 2:
   case 3:
      fprintf(stderr, "Error type);
   }
}

The following example shows a more complex custom reporting function. In this example, the switch statement handles various error types, as defined by the reportType parameter of _CrtDbgReport. Since you are replacing _CrtDbgReport, you cannot use _CrtSetReportMode. Your function must handle the output. The first variable argument in this function takes a run-time error number.

#include <windows.h>
#include <stdarg.h>
#pragma runtime_checks("", off)
int Catch_RTC_Failure(int errType, const char *file, int line, const char *module, const char *format, ...)
{
   // Prevent re-entrancy
   static long running = 0;
   while (InterlockedExchange(&running, 1))
      Sleep(0);
   // Now, disable all RTC failures
   int numErrors = _RTC_GetNumErrors();
   int *errors=_alloca(numErrors);
   for (int i = 0; i < numErrors; i++)
   errors[i] = _RTC_SetErrorType(i, _RTC_ERRTYPE_IGNORE);

   // First, let's get the rtc error number from the var-arg list...
   va_list vl;
   va_start(vl, format);
   _RTC_ErrorNumber rtc_errnum = va_arg(vl, _RTC_ErrorNumber);
   va_end(vl);

   char buf[512];
   const char *err = _RTC_GetErrDesc(rtc_errnum);
   sprintf(buf, "%s\nLine #%d\nFile:%s\nModule:%s", 
      err, 
      line, 
      file ? file : "Unknown", 
      module ? module : "Unknown");
   int res = (MessageBox(NULL, buf, "RTC Failed...", MB_YESNO) == IDYES) ? 1 : 0;
   // Now, restore the RTC errortypes
   for(i = 0; i < numErrors; i++)
      _RTC_SetErrorType(i, errors[i]);
   running = 0;
   return res;
}
#pragma runtime_checks("", restore)

Use _RTC_SetErrorFunc to install your custom function in place of _CrtDbgReport. The _RTC_SetErrorFunc return value is the previous reporting function, which you can save and restore if necessary:

int main()
{
   _RTC_error_fn oldfunction, newfunc;
   oldfunction = _RTC_SetErrorFunc(&MyErrorFunc);
   // run some code...
   newfunc = _RTC_SetErrorFunc(oldfunction);
   // newfunc == &MyErrorFunc;
   // run some more code...
}

Customizing the Error Message Destination

If you use _CrtDbgReport to report errors, you can use _CrtSetReportMode to specify the destination of error messages.

If you use a custom reporting function, use _RTC_SetErrorType to associate an error with a report type.

Querying for Information about Run-Time Error Checks

_RTC_NumErrors returns the number of error types detect by run-time error checks. To get a brief description of each error, you can loop from 0 to (_RTC_NumErrors –1) return value, passing the iteration value to _RTC_GetErrDesc on each loop.